Jx.declare('Jx.platform.browser.lib.Event', {

	$singleton: true,
	
	$helpers: {
		
		'Dom': 'Jx.platform.browser.lib.Dom'
		
	},

	methods: [

		'addEvent',

		'removeEvent',

		'dispatchEvent'

	],

	defaultEventTypes: [

		'click',

		'mousedown',

		'mouseup',

		'mousemove',

		'keydown',

		'keyup',

		'keypress',

		'keypress'

	],

	eventTypesByName: undefined,
	
	data: undefined,
	
	testElements: undefined,

	constructor: function(){

		this.eventTypesByName = {};
		
		this.data = {};
		
		this.testElements = {};

		for(var types = this.defaultEventTypes, l = types.length; l--;){

			this.setEventType(types[l]);

		}

		this.$super(arguments);

	},

	getEventType: function(name){

		var types = this.eventTypesByName;

		return types.hasOwnProperty(name) ?

			types[name]

			:

			void(0);

	},

	getEventMethodNames: function(support){

		var prefix = support.is('domEventLevel2') ?

				'w3c'

				:

				support.is('domMSEvent') ?

					'ie'

					:

					'',

			methods = this.methods,

			alternatives = {};

		for(var name, l = methods.length; l--;){

			name = methods[l];

			alternatives[ name ] = prefix+'_'+name;

		}

		return alternatives;

	},
	
	setEventType: function(name, type){

		var types = this.eventTypesByName;

		return types[ name ] = Jx.isString(name, true) ?

			Jx.isString(type, true) ?

				type

				:

				name

			:

			void(0);

	},
	
	isSupported: function(dom, name){
		
		var Dom = this.$Dom,
		
			db = this.data,
			
			isDom = Dom.isDom(dom),
			
			isElement = isDom && dom.nodeType == 1,
			
			isView = Dom.isView(dom),
			
			isDocument = isDom && dom.nodeType == 9,
			
			tagName = isElement ?
				
				String(dom.tagName).toLowerCase()
				
				:
				
				isDocument ?
					
					'<document>'
					
					:
					
					isView ?
						
						'<view>'
						
						:
						
						false,
			
			flag;
		
		return tagName && Jx.isString(name, true) ?
			
			db.hasOwnProperty( flag = tagName+':'+name.toLowerCase() ) ?
			
				db[flag]
				
				:
				
				db[flag] = ( isElement ?
					
					this.testExistenceInElement(dom, name)
					
					:
					
					this.testExistence(dom, name)
					
				)
			
			:
			
			false;
		
	},
	
	testExistence: function(dom, name){
		
		return 'on'+name.toLowerCase() in dom;
		
	},
	
	testExistenceInElement: function(dom, name){
		
		var testElements = this.testElements,
		
			tagName = dom.tagName.toLowerCase();
		
		if (!testElements.hasOwnProperty(tagName)){
			
			testElements[tagName] = dom.ownerDocument.createElement(tagName);
			
		}
		
		return this.testExistence(testElements[tagName], name);
		
		
	},

/**
 *	W3C event
 */
	w3c_addEvent: function(dom, name, fn){

		dom.addEventListener(name, fn, false);

	},

	w3c_removeEvent: function(dom, name, fn){

		dom.removeEventListener(name, fn, false);

	},

	w3c_dispatchEvent: function(dom, eventObject){

		dom.dispatchEvent(eventObject);

	},

/**
 *	IE event methods
 */
	ie_addEvent: function(dom, name, fn){

		dom.attachEvent('on'+name, fn);

	},

	ie_removeEvent: function(dom, name, fn){

		dom.detachEvent('on'+name, fn);

	},

	ie_dispatchEvent: function(dom, eventObject){

		dom.fireEvent('on'+eventObject.type, eventObject);

	},

/**
 *	unsupported event methods
 */
	addEvent: function(){

	},

	removeEvent: function(){

	},

	dispatchEvent: function(){

	}

});
